package io.noties.markwon.base.html.tag

import io.noties.markwon.base.MarkwonVisitor
import io.noties.markwon.base.SpannableBuilder
import io.noties.markwon.base.core.CoreProps
import io.noties.markwon.base.html.*
import org.commonmark.node.ListItem

class ListHandler : TagHandler() {
    override fun handle(
        visitor: MarkwonVisitor,
        renderer: MarkwonHtmlRenderer,
        tag: HtmlTag
    ) {
        if (!tag.isBlock) {
            return
        }
        val block = tag.asBlock
        val ol = "ol" == block.name()
        val ul = "ul" == block.name()
        if (!ol && !ul) {
            return
        }
        val configuration = visitor.configuration()
        val renderProps = visitor.renderProps()
        val spanFactory = configuration.spansFactory(ListItem::class.java)
        var number = 1
        val bulletLevel = currentBulletListLevel(block)

        block.children().forEach { child ->
            if(child is HtmlTag.Block)
                visitChildren(visitor, renderer, child)
            spanFactory?.let {
                if("li" == child.name()){
                    if (ol) {
                        CoreProps.LIST_ITEM_TYPE[renderProps] = CoreProps.ListItemType.ORDERED
                        CoreProps. ORDERED_LIST_ITEM_NUMBER[renderProps] = number++
                    } else {
                        CoreProps.LIST_ITEM_TYPE[renderProps] = CoreProps.ListItemType.BULLET
                        CoreProps.BULLET_LIST_ITEM_LEVEL[renderProps] = bulletLevel
                    }
                    SpannableBuilder.setSpans(
                        visitor.builder(),
                        it.getSpans(configuration, renderProps),
                        child.start(),
                        child.end()
                    )
                }
            }
        }
    }

    override fun supportedTags(): List<String> {
        return LIST_TAGS
    }

    companion object {
        val LIST_TAGS=listOf("ol", "ul")

        private fun currentBulletListLevel(block: HtmlTag.Block): Int {
            var parent = block.parent()
            var level = 0
            while (parent != null) {
                if ( parent.name() in  LIST_TAGS) {
                    level += 1
                }
                parent = parent.parent()
            }
            return level
        }
    }
}